#include "Channel.hpp"
#include "Task.hpp"

class ProcessPool
{
public:
    ProcessPool(int size = 5)
        :_size(size)
    {
        std::cout << "ProcessPool已创建" << std::endl;
    }
    ~ProcessPool()
    {
        if(_activate)
        {
            _CM.CloseChannels();
            _CM.WaitProcesses();
        }
    }

    void Work(int rfd)
    {
        int code = 0;
        std::cout << "子进程" << getpid() << "开始工作" << std::endl;
        while(true)
        {
            ssize_t n = read(rfd, &code, sizeof(code));
            if(n == 0) 
            {
                std::cout << "进程" << getpid() << "退出" << std::endl;
                break;
            }
            else if(n < 0)
            {
                std::cout << "进程" << getpid() << "获取任务时发生错误" << std::endl;
                break;
            }
            else 
                _TM.GetTask(code)();
        }
    }

    void Start()
    {
        for(int i = 0; i < _size; i++)
        {
            int fds[2] = {0};
            int n = pipe(fds);
            if(n == -1)
            {
                perror("pipe:");
            }

            int id = fork();
            if(id < 0)
            {
                perror("fork:");
                exit(1);
            }
            else if(id == 0)
            {
                // 子进程
                close(fds[1]);
                // 将子进程的写入端全部关闭
                _CM.SubProcessCloseBrothers();
                Work(fds[0]);
                close(fds[0]);
                exit(0);
            }

            // 父进程
            close(fds[0]);
            _CM.Insert(Channel(fds[1], id));
        }
        _activate = true;
    }

    void LaunchTask(int code)
    {
        assert(code >= 0 && code <= _TM.Size());
        std::cout << "发布任务: " << code << std::endl;
        _CM.GiveTask(code);
    }

    void Stop()
    {
        // _CM.CloseChannels();
        // _CM.WaitProcesses();
        _CM.CloseAndWait();
        _activate = false;
    }

    void RegisterTask(Task&& task)
    {
        _TM.RegisterTask(std::forward<Task>(task));
    }
private:
    int _size;
    bool _activate = false;
    ChannelManager _CM;
    TaskManager _TM;
};